# SPDX-License-Identifier: Apache-2.0
VERSION = 0
PATCHLEVEL = 0
SUBLEVEL = 1
EXTRAVERSION = -rc1
NAME = Hurr durr I'ma ninja sloth

# *DOCUMENTATION*
# To see a list of typical targets execute "make help"

$(if $(filter __%, $(MAKECMDGOALS)), \
	$(error targets prefixed with '__' are only for internal use))

# That's our default target when none is given on the command line
PHONY := __all
__all:

# Do not use make's built-in rules and variables
# (this increases performance and avoids hard-to-debug behaviour)
MAKEFLAGS += -rR

# Avoid funny character set dependencies
unexport LC_ALL
LC_COLLATE=C
LC_NUMERIC=C
export LC_COLLATE LC_NUMERIC

# Avoid interference with shell env settings
unexport GREP_OPTIONS

ifeq ("$(origin V)", "command line")
  KBUILD_VERBOSE = $(V)
endif
ifndef KBUILD_VERBOSE
  KBUILD_VERBOSE = 0
endif

ifneq ($(KBUILD_VERBOSE),0)
  Q =
else
  Q = @
endif

# If the user is running make -s (silent mode), suppress echoing of
# commands

ifneq ($(findstring s,$(filter-out --%,$(MAKEFLAGS))),)
  KBUILD_VERBOSE = 0
endif

export quiet Q KBUILD_VERBOSE

this-makefile := $(lastword $(MAKEFILE_LIST))
abs_srctree := $(realpath $(dir $(this-makefile)))

ifneq ($(words $(subst :, ,$(abs_srctree))), 1)
$(error source directory cannot contain spaces or colons)
endif

abs_objtree := $(shell mkdir -p $(abs_srctree)/target && pwd)/target
# $(realpath ...) resolves symlinks
abs_objtree := $(realpath $(abs_objtree))

# Suppress "Entering directory ..." unless we are changing the work directory.
MAKEFLAGS += --no-print-directory
# Look for make include files relative to root of kernel src
#
# --included-dir is added for backward compatibility, but you should not rely on
# it. Please add $(srctree)/ prefix to include Makefiles in the source tree.
MAKEFLAGS += --include-dir=$(abs_srctree)

export abs_srctree abs_objtree

srctree := .
objtree := target
VPATH	:= $(srctree)

export srctree objtree VPATH

clean-targets := %clean
no-dot-config-targets := $(clean-targets) help% doc% kernelversion

config-build :=
mixed-build :=
need-config := 1

ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),)
	ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),)
		need-config :=
	endif
endif

ifneq ($(filter %config,$(MAKECMDGOALS)),)
	config-build := 1
	ifneq ($(words $(MAKECMDGOALS)),1)
		mixed-build := 1
	endif
endif

# For "make -j clean all", "make -j clean defconfig all", etc.
ifneq ($(filter $(clean-targets),$(MAKECMDGOALS)),)
	ifneq ($(filter-out $(clean-targets),$(MAKECMDGOALS)),)
		mixed-build := 1
	endif
endif

ifdef mixed-build
# ===========================================================================
# We're called with mixed targets (*config and build targets).
# Handle them one by one.

PHONY += $(MAKECMDGOALS) __build_one_by_one

$(MAKECMDGOALS): __build_one_by_one
	@:

__build_one_by_one:
	$(Q)set -e; \
	for i in $(MAKECMDGOALS); do \
		$(MAKE) -f $(srctree)/Makefile $$i; \
	done

else # !mixed-build

KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION)
export VERSION PATCHLEVEL SUBLEVEL KERNELVERSION

# SHELL used by kbuild
CONFIG_SHELL := sh
CARGO := cargo
BINDGEN := bindgen

CARGO_OPTIONS :=
CARGO_FEATURES :=

export CONFIG_SHELL CARGO BINDGEN
export CARGO_OPTIONS CARGO_FEATURES

KCONFIG_OUTPUT := $(objtree)/config
# kconfiglib 使用该变量
KCONFIG_CONFIG := $(KCONFIG_OUTPUT)/.config
KCONFIG_AUTOCONF := $(KCONFIG_OUTPUT)/deps/auto.conf
KCONFIG_AUTOCONF_H := $(KCONFIG_OUTPUT)/autoconf.h
KCONFIG_CONFIG_BINGEN_H := $(abs_objtree)/config/config_bindings.rs
KCONFIG_FEATURES := $(KCONFIG_OUTPUT)/features.conf
export KCONFIG_OUTPUT KCONFIG_CONFIG KCONFIG_AUTOCONF KCONFIG_AUTOCONF_H
export KCONFIG_CONFIG_BINGEN_H KCONFIG_FEATURES

ifeq ($(KBUILD_VERBOSE),1)
CARGO_OPTIONS += -v
else ifeq ($(KBUILD_VERBOSE),2)
CARGO_OPTIONS += -vv
endif

ifdef config-build

%config: FORCE
	$(Q)mkdir -p $(KCONFIG_OUTPUT)
	$(Q)rm -rf $(srctree)/.cargo
	$(Q)$(CARGO) run $(CARGO_OPTIONS) --no-default-features --bin config -- $@
	$(Q)$(BINDGEN) $(KCONFIG_AUTOCONF_H) --use-core -o $(KCONFIG_CONFIG_BINGEN_H)
	$(Q)mkdir -p .cargo
	$(Q)mv $(KCONFIG_OUTPUT)/tmp_config.toml $(srctree)/.cargo/config.toml

else #!config-build

PHONY += all
__all: all

ifdef need-config

include $(KCONFIG_AUTOCONF)

CARGO_FEATURES += --features "config/need_config"
include $(KCONFIG_FEATURES)

$(KCONFIG_CONFIG):
	@echo >&2 '***'
	@echo >&2 '*** Configuration file "$@" not found!'
	@echo >&2 '***'
	@echo >&2 '*** Please run some configurator (e.g. "make oldconfig" or'
	@echo >&2 '*** "make menuconfig" or "make guiconfig").'
	@echo >&2 '***'
	@false

PHONY += $(KCONFIG_AUTOCONF) $(KCONFIG_FEATURES)
$(KCONFIG_AUTOCONF) $(KCONFIG_FEATURES): $(KCONFIG_CONFIG)
	$(Q)test -e $(KCONFIG_AUTOCONF_H) -a -e $@ || (		\
	echo >&2;							\
	echo >&2 "  ERROR: Kernel configuration is invalid.";		\
	echo >&2 "         $(KCONFIG_AUTOCONF_H) or $@ are missing.";\
	echo >&2 "         Run 'make oldconfig' on kernel src to fix it.";	\
	echo >&2 ;							\
	false)

endif # need-config

all: seminix
seminix: seloader kernel FORCE

seloader: FORCE
	$(Q)$(CARGO) build $(CARGO_OPTIONS) $(CARGO_FEATURES) --bin seloader

kernel: FORCE
	$(Q)$(CARGO) build $(CARGO_OPTIONS) $(CARGO_FEATURES) --bin kernel

run: FORCE
	$(Q)$(CARGO) run $(CARGO_OPTIONS) $(CARGO_FEATURES) --bin seloader

PHONY += kernelversion
kernelversion:
	@echo $(KERNELVERSION)

PHONY += help
help:
	@echo  'Cleaning targets:'
	@echo  '  clean           - Remove all generated files + config'
	@echo  ''
	@echo  'Configuration targets:'
	@echo  '  menuconfig      - Update current config utilising a menu based program'
	@echo  '  guiconfig       - Update current config utilising a GTK+ based program'
	@echo  '  oldconfig       - Update current config utilising a provided .config as base'
	@echo  '  savedefconfig   - Save current config as ./defconfig (minimal config)'
	@echo  '  allnoconfig	  - New config where all options are answered with no'
	@echo  '  allyesconfig	  - New config where all options are accepted with yes'
	@echo  '  alldefconfig    - New config with all symbols set to default'
	@echo  '  listnewconfig   - List new options'
	@echo  '  olddefconfig	  - Same as oldconfig but sets new symbols to their'
	@echo  '                    default value without prompting'
	@echo  ''
	@echo  'Other generic targets:'
	@echo  '  all             - Build all targets marked with [*]'
	@echo  '* seminix         - Build the bare kernel'
	@echo  '  kernelversion   - Output the version stored in Makefile (use with make -s)'
	@echo  '  make V=0|1 [targets] 0 => quiet build (default), 1 => verbose build'
	@echo  '  make V=2   [targets] 2 => give more info of target'
	@echo  ''
	@echo  'Execute "make" or "make all" to build all targets marked with [*] '
	@echo  'For further info see the ./README.md file'

PHONY += clean
clean:
	$(Q)rm -rf .cargo
	$(Q)$(CARGO) clean

endif # config-build
endif # mixed-build

PHONY += FORCE
FORCE:

# Declare the contents of the PHONY variable as phony.  We keep that
# information in a variable so we can use it in if_changed and friends.
.PHONY: $(PHONY)
